<?php
namespace addons\csmonline;

use app\common\library\Menu;
use think\Addons;
use app\common\library\Auth;
use think\Request;
use think\Session;
use fast\Random;

/**
 * 插件
 */
class Csmonline extends Addons
{

    /**
     * 插件安装方法
     *
     * @return bool
     */
    public function install()
    {
        $menu = [
            [
                'name' => 'csmonline',
                'title' => '在线人数和会员注册分析',
                'sublist' => [
                    [
                        'name' => 'csmonline/charthome/index',
                        'title' => '统计首页',
                        'weigh' => '590',
                        'sublist' => [
                            [
                                'name' => 'csmonline/charthome',
                                'title' => '查看'
                            ]
                        ]
                    ],
                    [
                        'name' => 'csmonline/crontab/run',
                        'title' => '手动运行定时器',
                        'weigh' => '580',
                        'sublist' => [
                            [
                                'name' => 'csmonline/crontab',
                                'title' => '查看'
                            ]
                        ]
                    ],
                    [
                        'name' => 'csmonline/chartregister2',
                        'title' => '注册会员',
                        'weigh' => '540',
                        'sublist' => [
                            [
                                'name' => 'csmonline/chartregister/index',
                                'title' => '会员注册整体分析',
                                'weigh' => '590',
                                'sublist' => [
                                    [
                                        'name' => 'csmonline/chartregister',
                                        'title' => '查看'
                                    ]
                                ]
                            ],
                            [
                                'name' => 'csmonline/chartregisterdate/index',
                                'title' => '会员注册分析(按日)',
                                'weigh' => '580',
                                'sublist' => [
                                    [
                                        'name' => 'csmonline/chartregisterdate',
                                        'title' => '查看'
                                    ]
                                ]
                            ],
                            [
                                'name' => 'csmonline/chartregisterweekend/index',
                                'title' => '会员注册分析(按周)',
                                'weigh' => '570',
                                'sublist' => [
                                    [
                                        'name' => 'csmonline/chartregisterweekend',
                                        'title' => '查看'
                                    ]
                                ]
                            ],
                            [
                                'name' => 'csmonline/chartregisterhour/index',
                                'title' => '会员注册分析(按小时)',
                                'weigh' => '560',
                                'sublist' => [
                                    [
                                        'name' => 'csmonline/chartregisterhour',
                                        'title' => '查看'
                                    ]
                                ]
                            ],
                            [
                                'name' => 'csmonline/fauser/index',
                                'title' => '会员注册明细数据',
                                'weigh' => '550',
                                'sublist' => [
                                    [
                                        'name' => 'csmonline/fauser',
                                        'title' => '查看'
                                    ]
                                ]
                            ]
                        ]
                    ],
                    [
                        'name' => 'csmonline/chartonline2',
                        'title' => '在线人数',
                        'weigh' => '550',
                        'sublist' => [
                            [
                                'name' => 'csmonline/chartonline/index',
                                'title' => '在线用户整体分析',

                                'weigh' => '500',
                                'sublist' => [
                                    [
                                        'name' => 'csmonline/chartonline',
                                        'title' => '查看'
                                    ]
                                ]
                            ],
                            [
                                'name' => 'csmonline/tableonline/index',
                                'title' => '在线用户列表',
                                'weigh' => '590',
                                'sublist' => [
                                    [
                                        'name' => 'csmonline/tableonline',
                                        'title' => '查看'
                                    ]
                                ]
                            ],
                            [
                                'name' => 'csmonline/chartonlinedate/index',
                                'title' => '在线用户统计(按日)',
                                'weigh' => '580',
                                'sublist' => [
                                    [
                                        'name' => 'csmonline/chartonlinedate',
                                        'title' => '查看'
                                    ]
                                ]
                            ],
                            [
                                'name' => 'csmonline/chartonlineweekend/index',
                                'title' => '在线用户统计(按周)',
                                'weigh' => '570',
                                'sublist' => [
                                    [
                                        'name' => 'csmonline/chartonlineweekend',
                                        'title' => '查看'
                                    ]
                                ]
                            ],
                            [
                                'name' => 'csmonline/chartonlinehour/index',
                                'title' => '在线用户统计(按小时)',
                                'weigh' => '560',
                                'sublist' => [
                                    [
                                        'name' => 'csmonline/chartonlinehour',
                                        'title' => '查看'
                                    ]
                                ]
                            ],
                            [
                                'name' => 'csmonline/tableenv/index',
                                'title' => '在线用户设备分析',
                                'weigh' => '550',
                                'sublist' => [
                                    [
                                        'name' => 'csmonline/tableenv',
                                        'title' => '查看'
                                    ]
                                ]
                            ],
                            [
                                'name' => 'csmonline/userlog/index',
                                'title' => '在线用户明细数据',
                                'weigh' => '540',
                                'sublist' => [
                                    [
                                        'name' => 'csmonline/userlog',
                                        'title' => '查看'
                                    ]
                                ]
                            ]
                        ]
                    ]
                ]
            ]
        ];
        Menu::create($menu);
        return true;
    }

    /**
     * 插件卸载方法
     *
     * @return bool
     */
    public function uninstall()
    {
        Menu::delete("csmonline");
        return true;
    }

    /**
     * 插件启用方法
     *
     * @return bool
     */
    public function enable()
    {
        Menu::enable("csmonline");
        return true;
    }

    /**
     * 插件禁用方法
     *
     * @return bool
     */
    public function disable()
    {
        Menu::disable("csmonline");
        return true;
    }

    public function viewFilter(&$content)
    {
        $request = Request::instance();
        $baseurl = $request->baseUrl();
        // 埋点后台访问不统计
        if (strpos($baseurl, "csmonline/index/touch") !== false) {
            return;
        }
        // 后台管理不统计
        if ($request->module() == 'admin') {
            return;
        }
        $config = get_addon_config("csmonline");
        $heartseconds = (int) $config["heartseconds"];
        $heartmseconds = $heartseconds * 1000;
        $preventrefreshseconds = (int) $config["preventrefreshseconds"];
        $preventrefreshcounts = (int) $config["preventrefreshcounts"];

        if ($this->_dz_checkrobot($request->server('HTTP_USER_AGENT'))) {
            // 如果是蜘蛛,则不埋点
            return;
        }

        if ($this->_islegalvisit($preventrefreshseconds, $preventrefreshcounts) === false) {
            // 如果非法，则不埋点
            return;
        }

        $point = $this->_setPagePoint();
        $url = $_SERVER["REQUEST_SCHEME"] . "://" . $_SERVER["SERVER_NAME"] . config('view_replace_str.__PUBLIC__') . 'addons/csmonline/index/touch?id=' . $point['id'] . '&sign=' . md5($point['id']);
        $js = '<script>function csmonline_get(url){xmlhttp=null;if (window.XMLHttpRequest){xmlhttp=new XMLHttpRequest();}else if (window.ActiveXObject){xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");}if(xmlhttp!=null){xmlhttp.onreadystatechange=csmonline_getstate_Change;xmlhttp.open("GET",url,true);xmlhttp.send(null);}else{console.log("Your browser does not support XMLHTTP.");}}function csmonline_getstate_Change(){if (xmlhttp.readyState==4){if (xmlhttp.status==200){}else{console.log("Problem retrieving XML data");}}}setInterval(function () {csmonline_get("' . $url . '&title="+escape(document.title));}, ' . $heartmseconds . ');</script>';
        $this->_appendtouchjs($content, $js);
    }

    /**
     * 检测是否合法
     * 通过sessionn中写入最近n次访问的时间戳，然后比较第一次的时间差
     * session#csmonline_preventkey 就记录了N次的访问的时间戳 A,B,C,D,E
     * 返回true或false
     */
    private function _islegalvisit($preventrefreshseconds, $preventrefreshcounts)
    {
        // 0秒则为不检测
        if ($preventrefreshseconds == 0) {
            return true;
        }
        // 开始检测
        // session_start();
        $preventkey = Session::get("csmonline_preventkey");
        // var_dump("get=".$preventkey);

        $now = time();
        $sr = true;
        if ($preventkey == null || $preventkey == "") {
            // 如果第一次则直接认定合法
            // var_dump("preventkey==null");
            $sr = true;
        } else {
            $records = explode(',', $preventkey);
            if (count($records) < $preventrefreshcounts) {
                // var_dump("count(records)<=preventrefreshcounts=".count($records).'/'.$preventrefreshcounts);
                // 如果记录的请求次数未到,则认定为合法
                $sr = true;
            } else {
                $firsttime = (int) $records[0];
                $septime = ($now - $firsttime);
                // var_dump("septime=".$septime);
                // var_dump("preventrefreshseconds=".$preventrefreshseconds);
                if ($septime < $preventrefreshseconds) {
                    // 请求第一次的时间是否超过了限定时间,则非法
                    $sr = false;
                } else {
                    $sr = true;
                }
            }
        }

        // 记录session时间戳
        $records[] = $now;
        // var_dump($records);
        // 如果session时间戳记录数未到,则全部写入;如果满了,则获取第二条到n+1
        if (count($records) <= $preventrefreshcounts) {
            $preventkey = implode(",", $records);
        } else {
            $preventkey = implode(",", array_slice($records, 1, $preventrefreshcounts + 1));
        }
        Session::set("csmonline_preventkey", $preventkey);
        // var_dump("set=".$preventkey);
        // var_dump($sr);
        return $sr;
    }

    // 增加埋点代码
    private function _appendtouchjs(&$content, $js)
    {
        $result = strripos($content, "</body>", - 1);
        if ($result === false) {
            $content .= '' . $js;
        } else {
            $content = substr_replace($content, $js . '</body>', $result, 7);
        }
    }

    public function _setPagePoint()
    {
        $request = Request::instance();
        $dao = new \app\admin\model\csmonline\Userlog();

        // 记录浏览器标记,如果get传输browserid，就以客户端的为准，否则自动生成
        $browserid = null;
        if (true) {
            $browserid = (int)$request->request('browserid');
            if ($browserid == null || $browserid == 0) {
                $browserid = Cookie("csmonline_browserid");
                //var_dump($browserid);die();
                if ($browserid == null || $browserid == "") {
                    $browserid = time() * 1000 + Random::numeric(3);  
                }
            }
            Cookie("csmonline_browserid", $browserid);
        }
 

        $cookieid = cookie("csmonline_cookieid");
        $cookieidvisitdeep = cookie("csmonline_cookieid_visitdeep");
        if ($cookieid == null || $cookieid == "") {
            $cookieid = time();
            $cookieidvisitdeep = 1;
            cookie("csmonline_cookieid", $cookieid);
            cookie("csmonline_cookieid_visitdeep", $cookieidvisitdeep);
        } else {
            $cookieidvisitdeep = (int) $cookieidvisitdeep;
            cookie("csmonline_cookieid_visitdeep", $cookieidvisitdeep);
        }

        $statdate = date("Y-m-d");
        $now = time();
        $nowhour = date("H");

        $baseurl = null;
        // 获取baseurl，如果是point过来的类型，则认为是前端访问，则真实的地址为?page=xxxx @csmonline 1.0.2
        if (true) {
            if (strpos($request->baseUrl(), "csmonline/index/point") !== false) {
                $baseurl = $request->get('page', '');
            } else {
                $baseurl = $request->baseUrl();
            }
        }

        $param = [
            "ip" => $request->ip(),
            "browserid" => $browserid,
            "visitid" => $now,
            "url" => $baseurl,
            "md5url" => md5($baseurl),
            "querystring" => $request->query(),
            "useragent" => substr($request->server('HTTP_USER_AGENT'), 0, 255),
            "createtime" => time(),
            "createdate" => $statdate,
            "createhour" => $nowhour,
            "createweekday" => date("w"),
            "sessionid" => $cookieid,
            "visitdeep" => $cookieidvisitdeep,
            "iscal" => "N",
            "durationseconds" => 0,
            'durationlasttime' => $now,
            'durationlasthour' => $nowhour
        ];
        $auth = Auth::instance();
        $user = $auth->getUser();
        $requestuesrid = (int)$request->get('userid');
        if ($auth->isLogin() == 'Y') {
            $param['isloginuser'] = 'Y';
            $param['user_id'] = $user->id;
            $param['userid'] = $user->id;
            $param['username'] = $user->username;
            $param['useridmd5url'] = $param['userid'] . $param['md5url'];
        } else if ($requestuesrid != null && $requestuesrid != 0) {
            //v1.0.2
            $param['isloginuser'] = 'Y';
            $param['user_id'] = $requestuesrid;
            $param['userid'] = $requestuesrid;
            $param['username'] = $request->get('username');
            $param['useridmd5url'] = $requestuesrid . $param['md5url'];
            
        } else {
            $username = '游客';
            //v1.0.2
            if (strpos($request->baseUrl(), "csmonline/index/point") !== false) {
                $username = $request->get('username', '游客');
            }

            $param['isloginuser'] = 'N';
            $param['userid'] = $param['browserid']; // 如果名用户，则以浏览器标记作为用户名
            $param['username'] = $username;
            $param['useridmd5url'] = $param['userid'] . $param['md5url'];
        }
        $dao->create($param);
        $id = $dao->getLastInsID();

        // 写入当天第一条ID
        $daofid = new \app\admin\model\csmonline\Firstid();
        $rowfid = $daofid->where("statdate", "=", $statdate)->find();
        if (! $rowfid) {
            $param = [
                "statdate" => $statdate,
                "firstid" => $id
            ];
            $daofid->create($param);
        }

        $sr = [
            'id' => $id
        ];
        return $sr;
    }

    // 判断是否是机器人(来自DZ)
    private function _dz_checkrobot($useragent = '')
    {
        static $kw_spiders = array(
            'bot',
            'crawl',
            'spider',
            'slurp',
            'sohu-search',
            'lycos',
            'robozilla'
        );
        static $kw_browsers = array(
            'msie',
            'netscape',
            'opera',
            'konqueror',
            'mozilla'
        );
        $useragent = strtolower(empty($useragent) ? $_SERVER['HTTP_USER_AGENT'] : $useragent);
        if (strpos($useragent, 'http://') === false && $this->_dz_dstrpos($useragent, $kw_browsers)) {
            return false;
        }
        if ($this->_dz_dstrpos($useragent, $kw_spiders)) {
            return true;
        }
        return false;
    }

    // 判断是否是机器人#依赖方法(来自DZ)
    private function _dz_dstrpos($string, $arr, $returnvalue = false)
    {
        if (empty($string)) {
            return false;
        }
        foreach ((array) $arr as $v) {
            if (strpos($string, $v) !== false) {
                $return = $returnvalue ? $v : true;
                return $return;
            }
        }
        return false;
    }
}

